#ifndef _ACSREG_H
#define _ACSREG_H

#define ARCH_IO8_WRITE(ioaddr, val)                 \
    __asm__ __volatile__                            \
        (                                           \
        "strb %[_val], [%[_ioaddr]] \n\t"           \
        :                                           \
        : [_val] "r" (val), [_ioaddr] "r" (ioaddr)  \
        : "memory"                                  \
        );

#define ARCH_IO8_READ(ioaddr, retdata)              \
    __asm__ __volatile__                            \
        (                                           \
        "ldrb %[_retdata], [%[_ioaddr]] \n\t"       \
        : [_retdata] "=r" (retdata)                 \
        : [_ioaddr] "r" (ioaddr)                    \
        : "memory"                                  \
        );
        

#define ARCH_IO16_WRITE(ioaddr, val)                 \
    __asm__ __volatile__                             \
        (                                            \
        "strh %[_val],[%[_ioaddr]] \n\t"             \
        :                                            \
        : [_val] "r" (val), [_ioaddr] "r" (ioaddr)   \
        : "memory"                                   \
        );

#define ARCH_IO16_READ(ioaddr, retdata)              \
    __asm__ __volatile__                             \
        (                                            \
        "ldrh %[_retdata], [%[_ioaddr]] \n\t"        \
        : [_retdata] "=r" (retdata)                  \
        : [_ioaddr] "r" (ioaddr)                     \
        : "memory"                                   \
        );

#define ARCH_IO32_WRITE(ioaddr, val)                 \
    __asm__ __volatile__                             \
        (                                            \
        "str %[_val], [%[_ioaddr]] \n\t"             \
        :                                            \
        : [_val] "r" (val), [_ioaddr] "r" (ioaddr)   \
        : "memory"                                   \
        );

#define ARCH_IO32_READ(ioaddr, retdata)              \
    __asm__ __volatile__                             \
        (                                            \
        "ldr %[_retdata], [%[_ioaddr]] \n\t"         \
        : [_retdata] "=r" (retdata)                  \
        : [_ioaddr] "r" (ioaddr)                     \
        : "memory"                                   \
        );

#define ARCH_SPINLOCK_INIT(lock)                          \
    __asm__ __volatile__                                  \
        (                                                 \
        "swp %[lockval], %[lockval], [%[lockadr]] \n\t"   \
        :                                                 \
        : [lockval] "r" (0), [lockadr] "r" (&lock->value) \
        : "memory"                                        \
        );
        
#define ARCH_SPINLOCK_LOCK(lock)                        \
    __asm__ __volatile__                                \
        (                                               \
        "mov r8, #1 \n\t"                               \
        "1:swp r7, r8, [%[lockadr]] \n\t"               \
        "cmp r7, #0 \n\t"                               \
        "bne 1b \n\t"                                   \
        :                                               \
        : [lockadr] "r" (&lock->value)                  \
        : "r7", "r8", "cc", "memory"                    \
        );
        
#define ARCH_SPINLOCK_UNLOCK(lock)                        \
    __asm__ __volatile__                                  \
        (                                                 \
        "swp %[lockval], %[lockval], [%[lockadr]] \n\t"   \
        :                                                 \
        : [lockval] "r"(0), [lockadr] "r" (&lock->value)  \
        : "memory"                                        \
        );
        
#define ARCH_IRQ_DISABLE_SAVECPUFLG(tmpcpsr)      \
    __asm__ __volatile__                         \
        (                                        \
        "mrs r7, cpsr \n\t"                      \
        "mov %[tmpcpr], r7 \n\t"                 \
        "orr r7, r7, %[closeirq] \n\t"           \
        "msr cpsr, r7 \n\t"                      \
        : [tmpcpr] "=r" (tmpcpsr)                \
        : [closeirq] "I" (CIRQ)                  \
        : "r7", "cc", "memory"                   \
        );
        
#define ARCH_IRQ_ENABLE_RESTCPUFLG(cpuflg)       \
    __asm__ __volatile__                        \
        (                                       \
        "msr cpsr, %[ordcpr] \n\t"              \
        :                                       \
        : [ordcpr] "r" (*cpuflg)                \
        : "cc", "memory"                        \
        );
        
        
#define ARCH_SPINLOCK_SAVEFLG_CLI_1(tmpcpsr)      \
    __asm__ __volatile__                 \
        (                                \
         "mrs r7, cpsr \n\t"             \
         "mov %[tmpcpr], r7 \n\t"      /* 保存 CPSR 寄存器的值到 tmpcpsr 变量中 */  \
         "orr r7, r7, %[closefirq] \n\t" \
         "msr cpsr, r7 \n\t"           /* 失能 IRQ、FRQ 中断 */  \
         : [tmpcpr] "=r" (tmpcpsr)       \
         : [closefirq] "I" (CIRQFIQ)     \
         : "r7", "cc", "memory"          \
        );
        
#define ARCH_SPINLOCK_SAVEFLG_CLI_2(lock)        \
    __asm__ __volatile__                   \
        (                                  \
         "mov r8, #1 \n\t"                 \
         "1:swp r7, r8, [%[lockadr]] \n\t" /* 原子交换自旋锁的锁值 */ \
         "cmp r7, #0 \n\t"                 /* 比较换回的锁值是否为0 */ \
         "bne 1b \n\t"                     /* 如果换回的锁值为0，则返回，否则跳回到 标号1 处继续交换 */ \
         :                                 \
         : [lockadr] "r" (&lock->value)    \
         : "r7", "r8", "cc", "memory"      \
        );
        
#define ARCH_SPINUNLOCK_RESTFLG_STI_1(lock)                     \
    __asm__ __volatile__                                  \
        (                                                 \
         "swp %[lockval], %[lockval], [%[lockadr]] \n\t" /* 把 0值 换回自旋锁锁中, 表示解锁 */ \
         :                                                \
         : [lockval] "r"(0), [lockadr] "r" (&lock->value) \
         : "memory"                                       \
        );
        
#define ARCH_SPINUNLOCK_RESTFLG_STI_2(cpuflg) \
    __asm__ __volatile__              \
        (                             \
         "msr cpsr, %[ordcpr] \n\t"  /* 恢复保存在 cpuflg 地址处的值到 cpsr 寄存器中 */ \
         :                            \
         : [ordcpr] "r" (*cpuflg)     \
         : "cc", "memory"             \
        );

#endif
